#ifndef __COMMON_H__
#define __COMMON_H__

typedef enum {false, true} bool;

/* 符号类型 */
typedef enum {
    nul,          // 空
    ident,        // 标识符
    number,       // 数字
    plus,         // 加法 +
    minus,        // 减法 -
    times,        // 乘法 *
    slash,        // 除法 /
    mod,          // 取余 %
    and,          // 与 &
    or,           // 或 |
    not,          // 非 !
    eql,          // 等于 ==
    neq,          // 不等于 !=
    lss,          // 小于 <
    leq,          // 小于等于 <=
    gtr,          // 大于 >
    geq,          // 大于等于 >=
    lparen,       // 左括号 (
    rparen,       // 右括号 )
    lpar,         // 左括号 [
    rpar,         // 右括号 ]
    begin,        // 开始 {
    end,          // 结束 }
    comma,        // 逗号 ,
    semicolon,    // 分号 ;
    point,        // 结构体内成员 .
    becomes,      // 赋值 =
    ifsym,        // 判断 "if"
    elsesym,      // 否则 "else"
    whilesym,     // 循环 "while"
    forsym,       // 循环 "for"
    readsym,      // int输入 "scan"
    writesym,     // int输出 "print"
    breadsym,     // bool输入 "bscan"
    bwritesym,    // bool输出 "bprint"
    boolsym,      // 变量 "bool"
    intsym,       // 变量 "int"
    structsym,    // 结构体 "struct"
    voidsym,      // 无返回值 "void"
    procsym,      // 函数 "procedure"
    truesym,      // bool "true"
    falsesym,     // bool "false" 
    mainsym,      // 函数 "main"
    callsym,      // 调用 "call"
    returnsym,    // 返回 "return"
} symbol;

#define symnum   45     // 符号类型数
#define norw     18     // 保留字类型数

/* 符号表中类型 */
typedef enum {
    var_int,
    var_bool,
    var_struct,
    procedure,
} object;

typedef struct {
    char structname[16];      // 这个结构体的名字
    int structsize;           // 结构体的大小
    
    char member_name[5][16];  // 成员变量们的名字
    object member_kind[5];    // 成员变量们的类型
    int member_len[5][5];     // 成员变量们的长度
    int member_offset[5];     // 成员变量们的偏移量信息
    int member_count;         // 成员变量的数目(最多五个)
} struct_entry;

/* 符号表表项 */
typedef struct {
    char name[16];  // 符号名
    object kind;    // 符号类型
    int lev;        // 层数
    int adr;        // 层内地址
    int len[5];     // 多维数组的每维长度               数组支持
    int sid;        // struct_id in sturct_table       结构体支持
    bool isptr;     // 是指针吗                        指针支持
    int to_lev;     // 被指向者的层数
    int to_adr;     // 被指向者的地址
} table_entry;

/* Pcode操作码 */
typedef enum {
    lit,          // 立即数赋值
    opr,          // 各种操作
    lod,          // load
    sto,          // store
    cal,          // 函数调用
    ini,          // 开辟栈中空间(为了避免和int重名)
    jmp,          // 无条件跳转
    jpc,          // 条件跳转
} fct;

#define fctnum 8

/* pcode指令 */
typedef struct {
    fct op;       // 操作码
    int level;    // 层差
    int value;    // 操作数
} instruction;

/*------------------------------ 函数定义 -----------------------------*/

// 词法分析

void lex_init();
void lex_next();

// 报错

void panic(char* warning);
void assert(bool condition, char* warning);

// 语法分析

void block_init();
void block(int lev, int dx, int tx, bool have_return);

// 代码生成

void code_init();
void code_gen(object op, int level, int value);
instruction code_read(int p);
void code_list(int begin);

// 解释执行

void interpret();

#endif

/*
    opr 指令
    0  调用返回(无返回值)
    1  调用返回(有返回值)
    2  栈顶元素取负
    3  次栈顶 +  栈顶
    4  次栈顶 -  栈顶
    5  次栈顶 *  栈顶
    6  次栈顶 /  栈顶
    7  栈顶顶 %  栈顶
    8  次栈顶 == 栈顶 ? 1 : 0
    9  次栈顶 != 栈顶 ? 1 : 0
    10 次栈顶 <  栈顶 ? 1 : 0
    11 次栈顶 >= 栈顶 ? 1 : 0
    12 次栈顶 >  栈顶 ? 1 : 0
    13 次栈顶 <= 栈顶 ? 1 : 0
    14 输出 int (print)
    15 输入 int (scan)
    16 输出 bool (bprint)
    17 输入 bool (bscan)
    18 次栈顶 &  栈顶 (bool类型)
    19 次栈顶 |  栈顶 (bool类型)
    20 次栈顶 !  栈顶 (bool类型)
    21 函数传参 (栈顶元素放到指定位置)
*/